package com.fengye.common.utils;

import com.alibaba.fastjson.JSON;
import com.fengye.common.domain.dto.ResignIpaDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import javax.annotation.Nonnull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class ResignUtils {

    /**
     * 重签名ipa
     * @param resignIpaDto  参数
     * @return 是否签名成功
     * @throws IOException
     * @throws InterruptedException
     *
     * 命令示例：
     *      fastlane sigh resign Lark_7.1.23_269605796.ipa --signing_identity BE969EE1C22E5FD9F2ECAED494D324BD0F825A0F
     *      -p com.bytedance.ee.lark.broadcast=kld_feishu_private_broadcast_pp.mobileprovision
     *      -p com.bytedance.ee.lark.shareExtension=kld_feishu_private_share_pp.mobileprovision
     *      -p com.bytedance.ee.lark.notificationService=kld_feishu_private_notification_pp.mobileprovision
     *      -p com.bytedance.ee.lark=kld_feishu_private_pp.mobileprovision
     *      -p com.bytedance.ee.lark.intents=kld_feishu_private_intents_pp.mobileprovision
     *      -p com.bytedance.ee.lark.smartwidget=kld_feishu_private_smartWidget_pp.mobileprovision
     *      -p com.bytedance.ee.lark.notificationContent=kld_feishu_private_notificationContent_pp.mobileprovision
     *      -p com.bytedance.ee.lark.appintents=kld_feishu_private_appIntents_pp.mobileprovision -
     *      -use-app-entitlements
     * 参考:
     * <a href="https://www.jianshu.com/p/52deb349d5d1">...</a>
     *
     * 安装证书和描述文件：<a href="https://blog.csdn.net/xlyrh/article/details/109118189">...</a>
     */
    public static boolean resignIpa(ResignIpaDto resignIpaDto) {
        return executeCommand(constructResignCommand(resignIpaDto));
    }

    /**
     * 构造重签名shell命令字符串
     * @param resignIpaDto 重签名dto
     * @return shell命令字符串
     */
    private static String constructResignCommand(ResignIpaDto resignIpaDto) {
        List<String> commands = new ArrayList<>();

        // 添加基础的fastlane sigh resign命令
        commands.add("fastlane sigh resign");
        // 添加ipa路径
        commands.add(resignIpaDto.getIpaPath());
        // 添加签名身份
        commands.add("--signing_identity");
        commands.add(resignIpaDto.getSigningIdentity());
        // 添加每个插件的Provisioning Profile
        resignIpaDto.getProvisioningProfiles().forEach((bundleId, provisioningProfilePath) -> {
            commands.add("-p");
            String pp = String.format("%s=%s", bundleId, provisioningProfilePath);
            commands.add(pp);
        });
        // 使用app entitlements
        commands.add("--use-app-entitlements");

        // 添加额外参数
        if (!Objects.isNull(resignIpaDto.getExtraParamList()) && resignIpaDto.getExtraParamList().size() > 0) {
            commands.addAll(resignIpaDto.getExtraParamList());
        }

        // shell命令
        String commandsStr = commands.stream().collect(Collectors.joining(" "));
        log.info("执行shell命令：\n{}", commandsStr);

        return commandsStr;
    }

    /**
     * 在MacOS上安装苹果证书
     * 安装证书和描述文件：<a href="https://blog.csdn.net/xlyrh/article/details/109118189">...</a>
     * @param certificatePath 证书路径
     */
    public static boolean installCertificate(@Nonnull String certificatePath, String certificatePassword) {
        String commond = "security import" + certificatePath + " -k ~/Library/Keychains/login.keychain-db -P " + certificatePassword;
       return executeCommand(commond);
    }

    /**
     * 执行shell命令
     * @param command 命令
     * @return 是否执行成功
     */
    public static boolean executeCommand(String command) {
        // 创建ProcessBuilder对象
        ProcessBuilder processBuilder = new ProcessBuilder();
        Assert.notNull(command, "shell命令不能为空");
        // 此处记得加bash -c，不然如果命令太长，会报错： File name too long：63
        if (command.contains("bash -c")) {
            processBuilder.command(command);
        } else {
            processBuilder.command("bash", "-c", command);
        }

        // 标准错误将与标准输出合并
        processBuilder.redirectErrorStream(true);
        // 重定向到System.out;
        processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);

        try {
            // 开始执行shell命令
            Process process = processBuilder.start();
            // 读取并打印命令的输出
            String output = reader(process.getInputStream());
            log.info("命令log输出:\n" + output);

            // 如果exitCode==0，则表示执行成功，否则失败
            int exitCode = process.waitFor();
            log.info("shell命令：{}，退出码：{}", command, exitCode);

            return exitCode == 0;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return false;
    }

    /**
     * 读取shell命令日志
     * @param input 输出流
     * @return 日志
     */
    private static String reader(InputStream input) {
        StringBuilder output = new StringBuilder();
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                output.append(line).append("\n");
            }
        } catch (IOException e) {
            log.error("执行shell命令失败：", e);
        }
        return output.toString();
    }

    public static void main(String[] args) {

        String ipaPath = "/Users/sunlei/Desktop/resign/Lark_7.1.23_269605796.ipa";
        String signingIdentity = "BE969EE1C22E5FD9F2ECAED494D324BD0F825A0F";

        Map<String, String> provisioningProfileMap = new HashMap<>();
        provisioningProfileMap.put("com.bytedance.ee.lark.broadcast", "/Users/sunlei/Desktop/resign/kld_feishu_private_broadcast_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.shareExtension", "/Users/sunlei/Desktop/resign/kld_feishu_private_share_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.notificationService", "/Users/sunlei/Desktop/resign/kld_feishu_private_notification_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark", "/Users/sunlei/Desktop/resign/kld_feishu_private_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.intents", "/Users/sunlei/Desktop/resign/kld_feishu_private_intents_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.smartwidget", "/Users/sunlei/Desktop/resign/kld_feishu_private_smartWidget_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.notificationContent", "/Users/sunlei/Desktop/resign/kld_feishu_private_notificationContent_pp.mobileprovision");
        provisioningProfileMap.put("com.bytedance.ee.lark.appintents", "/Users/sunlei/Desktop/resign/kld_feishu_private_appIntents_pp.mobileprovision");

        ResignIpaDto resignIpaDto = new ResignIpaDto(ipaPath, signingIdentity, provisioningProfileMap, null);

        log.info(JSON.toJSONString(resignIpaDto, true));

        Boolean resignIPA = resignIpa(resignIpaDto);
        log.info("resignIPA = " + resignIPA);
    }
}
